package controller

// package controller/user.go
import (
	"bluebell/dao/mysql"
	"bluebell/logic"
	"bluebell/models"
	"bluebell/param"
	"bluebell/setting"
	"strconv"

	"encoding/json"
	"errors"
	"fmt"

	"math/rand"
	"time"

	"github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi"

	"github.com/go-playground/validator/v10"
	"go.uber.org/zap"

	"github.com/gin-gonic/gin"
)

const (
	mnsDomain = "1943695596114318.mns.cn-hangzhou.aliyuncs.com"
)

// GetPostsByUserIDHandler 根据用户ID获取帖子列表
// @Summary 根据用户ID获取帖子列表
// @Description 通过用户ID查询用户发布的帖子列表
// @Tags 帖子相关接口
// @Accept application/json
// @Produce application/json
// @Param Authorization header string true "Bearer JWT"
// @Param user_id path int true "用户ID"
// @Security ApiKeyAuth
// @Success 200 {object} models.ResponseSuccess
// @Success 400 {object} models.ResponseError "参数错误"
// @Success 500 {object} models.ResponseError "服务器错误"
// @Router /user/:user_id/posts [get]
func GetPostsByUserIDHandler(c *gin.Context) {
	// 1. 获取参数
	//  获取当前用户ID
	userID, err := getCurrentUserID(c)
	if err != nil {
		ResponseError(c, models.CodeNeedLogin)
		return
	}

	// 2. 调用逻辑层
	posts, err := logic.GetPostsByUserID(userID)
	if err != nil {
		zap.L().Error("logic.GetPostsByUserID failed", zap.Error(err))
		ResponseError(c, models.CodeServerBusy)
		return
	}

	// 3. 返回响应
	ResponseSuccess(c, posts)
}

// SignUpHandler 用户注册接口
// @Summary 用户注册接口
// @Description 注册用户账户
// @Tags 用户相关接口(api分组展示使用的)
// @Accept application/json
// @Produce application/json
// @Param Authorization header string true "Bearer JWT"
// @Param ParamSignUp body models.ParamSignUp true "用户注册参数"
// @Security ApiKeyAuth
// @Success 200 {object} models.ResponseSuccess "成功响应"
// @Success 400 {object} models.ResponseError "响应错误"
// @Success 500 {object} models.ResponseError "服务器错误"
// @Router /community/:id [post]
func SignUpHandler(c *gin.Context) {
	// 1. 获取参数和参数校验
	p := new(models.ParamSignUp)
	if err := c.ShouldBindJSON(p); err != nil {
		// 请求参数有误，直接返回响应
		zap.L().Error("SignUp with invalid param", zap.Error(err))
		// 判断err是不是validator.ValidationErrors 类型
		errs, ok := err.(validator.ValidationErrors)
		if !ok {
			ResponseError(c, models.CodeInvalidParam)
			return
		}
		ResponseErrorWithMsg(c, models.CodeInvalidParam, removeTopStruct(errs.Translate(trans)))
		return
	}
	// 2. 业务处理
	if err := logic.SignUp(p); err != nil {
		zap.L().Error("logic.SignUp failed", zap.Error(err))
		if errors.Is(err, mysql.ErrorUserExist) {
			ResponseError(c, models.CodeUserExist)
			return
		}
		ResponseError(c, models.CodeServerBusy)
		return
	}
	// 3. 返回响应
	ResponseSuccess(c, nil)
}

// LoginHandler 用户登录接口
// @Summary 用户登录接口
// @Description 登录用户账户
// @Tags 用户相关接口(api分组展示使用的)
// @Accept application/json
// @Produce application/json
// @Param Authorization header string true "Bearer JWT"
// @Param ParamLogin body models.ParamLogin true "用户登录参数"
// @Security ApiKeyAuth
// @Success 200 {object} models.ResponseSuccess "成功响应"
// @Success 400 {object} models.ResponseError "响应错误"
// @Success 500 {object} models.ResponseError "服务器错误"
// @Router /login [post]
func LoginHandler(c *gin.Context) {
	// 1.获取请求参数及参数校验
	p := new(models.ParamLogin)
	if err := c.ShouldBindJSON(p); err != nil {
		// 请求参数有误，直接返回响应
		zap.L().Error("Login with invalid param", zap.Error(err))
		// 判断err是不是validator.ValidationErrors 类型
		errs, ok := err.(validator.ValidationErrors)
		if !ok {
			ResponseError(c, models.CodeInvalidParam)
			return
		}
		ResponseErrorWithMsg(c, models.CodeInvalidParam, removeTopStruct(errs.Translate(trans)))
		return
	}
	// 2.业务逻辑处理
	user, err := logic.Login(p)
	if err != nil {
		zap.L().Error("logic.Login failed", zap.String("username", p.Username), zap.Error(err))
		if errors.Is(err, mysql.ErrorUserNotExist) {
			ResponseError(c, models.CodeUserNotExist)
			return
		}
		ResponseError(c, models.CodeInvalidPassword)
		return
	}

	// 3.返回响应
	ResponseSuccess(c, gin.H{
		"user_id":   fmt.Sprintf("%d", user.UserID), // id值大于1<<53-1  int64类型的最大值是1<<63-1
		"user_name": user.Username,
		"token":     user.Token,
		"user":      user,
	})
}

// GetUserPage 用户界面
// @Summary 用户界面
// @Description 完成用户页面
// @Tags 用户相关接口(api分组展示使用的)
// @Accept application/json
// @Produce application/json
// @Param Authorization header string true "Bearer JWT"
// @Param UserID query int true "用户ID"
// @Param CommentID query int true "帖子ID"
// @Security ApiKeyAuth
// @Success 200 {object} models.ResponseSuccess "成功响应"
// @Success 400 {object} models.ResponseError "响应错误"
// @Success 500 {object} models.ResponseError "服务器错误"
// @Router /userPage [get]
func GetUserPage(c *gin.Context) {
	userIDStr := c.Query("UserID")
	postIDStr := c.Query("CommentID")
	userID, err := strconv.ParseInt(userIDStr, 10, 64)
	if err != nil {
		zap.L().Error("get userID detail with invalid param")
		ResponseError(c, models.CodeInvalidParam)
		return
	}
	postID, err := strconv.ParseInt(postIDStr, 10, 64)
	if err != nil {
		zap.L().Error("get postID detail with invalid param")
		ResponseError(c, models.CodeInvalidParam)
		return
	}
	user, post := logic.GetUserPage(userID, postID)
	UserPage := models.UserPage{
		User: user,
		Post: post,
	}
	ResponseSuccess(c, UserPage)
}

// LoginSMSHandler 使用短信验证码登录
// @Summary 短信验证码接口
// @Description 使用阿里云短信服务SDK发送短信验证码
// @Tags 短信相关接口(api分组展示使用的)
// @Accept application/json
// @Produce application/json
// @Param Authorization header string true "Bearer JWT"
// @Param ParamLogin body models.ParamLogin true "用户登录参数"
// @Security ApiKeyAuth
// @Success 200 {object} models.ResponseSuccess "成功响应"
// @Success 400 {object} models.ResponseError "响应错误"
// @Success 500 {object} models.ResponseError "服务器错误"
// @Router /loginSMS [post]
func LoginSMSHandler(c *gin.Context) {
	// 获取参数
	var req struct {
		Phone string `json:"phone"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		ResponseError(c, models.CodeInvalidParam)
		zap.L().Error("ShouldBindJSON error", zap.Error(err))
		return
	}

	ms := setting.SMSConfig{
		RegionID:     "cn-hangzhou",
		AppKey:       "LTAI5tK8aEzjSq28FMWc9e1q",
		AppSecret:    "o959xbCUazNPEW1cZqU5zEW0VvINJm",
		SignName:     "风铃论坛",
		TemplateCode: "SMS_468420005",
	}

	// 生成六位数验证码
	code := fmt.Sprintf("%06v", rand.New(rand.NewSource(time.Now().UnixNano())).Int31n(1000000))

	// 创建client实例
	client, err := dysmsapi.NewClientWithAccessKey(
		ms.RegionID,  // 您的可用区ID
		ms.AppKey,    // 您的AccessKey CommentID
		ms.AppSecret) // 您的AccessKey Secret
	if err != nil {
		ResponseError(c, models.CodeServerBusy)
		zap.L().Error("Failed to create SMS client", zap.Error(err))
		return
	}
	request := dysmsapi.CreateSendSmsRequest()
	request.Scheme = "https"
	request.PhoneNumbers = req.Phone
	request.SignName = ms.SignName
	request.TemplateCode = ms.TemplateCode
	par, err := json.Marshal(map[string]interface{}{
		"code": code,
	})
	if err != nil {
		ResponseError(c, models.CodeServerBusy)
		zap.L().Error("Failed to marshal template param", zap.Error(err))
		return
	}
	request.TemplateParam = string(par)
	response, err := client.SendSms(request)
	if err != nil {
		zap.L().Error("client.SendSms(request) error", zap.Error(err))
		ResponseError(c, models.CodeServerBusy)
		return
	}

	fmt.Println(response)

	// 发送成功返回响应
	ResponseSuccess(c, nil)
}

func UpdateAvatarHandler(c *gin.Context) {
	var p param.UpdateAvatarParam
	if err := c.ShouldBindJSON(&p); err != nil {
		zap.L().Error("参数绑定失败", zap.Error(err))
		ResponseError(c, models.CodeInvalidParam)
		return
	}
	err := logic.UpdateAvatar(&p)
	if err != nil {
		ResponseError(c, models.CodeServerBusy)
		return
	}
	ResponseSuccess(c, nil)
}

func UpdateUsernameHandler(c *gin.Context) {
	var p param.UpdateUsernameParam
	if err := c.ShouldBindJSON(&p); err != nil {
		ResponseError(c, models.CodeInvalidParam)
		return
	}
	if err := logic.UpdateUsername(&p); err != nil {
		ResponseError(c, models.CodeServerBusy)
		return
	}
	ResponseSuccess(c, nil)
}
